package org.zsk.fastdev.assign.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zsk.fastdev.annotations.FieldMap;
import org.zsk.fastdev.assign.Assign;
import org.zsk.fastdev.common.StringOpt;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * <p>
 * 赋值工具类
 * </p>
 *
 * @author zsk
 * @version 1.0
 * Created on 2020/03/29
 */
public class AssignByAnnotation implements Assign {
    private final static Logger logger= LoggerFactory.getLogger(AssignByAnnotation.class);
    private final static AssignByAnnotation INSTANCE=new AssignByAnnotation();
    private AssignByAnnotation() {}
    public static AssignByAnnotation getInstance() {
        return INSTANCE;
    }

    @Override
    public void assign(Object assignBean,Object assignedBean) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class<?> assignClazz=assignBean.getClass();
        Class<?> assignedClazz=assignedBean.getClass();
        Field[] assignFields=assignClazz.getDeclaredFields();
        Method[] assignedMethods=assignedClazz.getDeclaredMethods();
        Field[] assignedFields=assignedClazz.getDeclaredFields();
        //第一个类的属性参数（值不为null或空）循环复制给第二个类相同属性参数
        for(int i=0;i<assignFields.length;i++) {
            Field field=assignFields[i];
            field.setAccessible(true);
            Object curVal=null;
            String fieldName="";
            Annotation fieldMapAnn=field.getDeclaredAnnotation(FieldMap.class);
            if (fieldMapAnn!=null){
                String tempFieldName=(String)(fieldMapAnn.annotationType()
                        .getMethod("mapFieldName").invoke(fieldMapAnn));
                if (tempFieldName.equals("*")){
                    fieldName=field.getName();
                } else if (tempFieldName != null && !"".equals(tempFieldName)){
                    fieldName=tempFieldName;
                }
            }else{
                fieldName=field.getName();
            }
            String methodName= StringOpt.getSetter(fieldName);
            Method curMethod=null;
            try {
                curMethod=assignedClazz.getDeclaredMethod(methodName,field.getType());
            }catch (NoSuchMethodException e){
                logger.debug("方法不存在:"+methodName);
            }
            if (curMethod!=null){
                logger.debug("当前方法："+curMethod.getName());
                curVal = field.get(assignBean);
                if(curVal!=null && !"".equals(curVal)) {
                    curMethod.invoke(assignedBean, curVal);
                    logger.debug("设值成功："+curVal);
                }
            }
        }
    }

    @Override
    public void assign(Object assignBean, Object assignedBean, String includeFieldName) throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Class<?> assignClazz=assignBean.getClass();
        Class<?> assignedClazz=assignedBean.getClass();
        Field[] assignFields=assignClazz.getDeclaredFields();
        Method[] assignedMethods=assignedClazz.getDeclaredMethods();
        Field[] assignedFields=assignedClazz.getDeclaredFields();
        String[] includeFieldNames=includeFieldName.split(",");
        //第一个类的属性参数（值不为null或空）循环复制给第二个类相同属性参数
        for(int i=0;i<includeFieldNames.length;i++) {
            Field field= null;
            boolean isNotNull=includeFieldNames[i].startsWith("$");
            //去除符号"$"
            if (isNotNull){
                field = assignClazz.getDeclaredField(includeFieldNames[i].substring(1));
            }else {
                field = assignClazz.getDeclaredField(includeFieldNames[i]);
            }
            field.setAccessible(true);
            Object curVal=null;
            String fieldName="";
            Annotation fieldMapAnn=field.getDeclaredAnnotation(FieldMap.class);
            if (fieldMapAnn!=null){
                String tempFieldName=(String)(fieldMapAnn.annotationType()
                        .getMethod("mapFieldName").invoke(fieldMapAnn));
                if (tempFieldName.equals("*")){
                    fieldName=field.getName();
                } else if (tempFieldName != null && !"".equals(tempFieldName)){
                    fieldName=tempFieldName;
                }
            }else{
                fieldName=field.getName();
            }
            String methodName= StringOpt.getSetter(fieldName);
            Method curMethod=null;
            try {
                curMethod=assignedClazz.getDeclaredMethod(methodName,field.getType());
            }catch (NoSuchMethodException e){
                logger.debug("方法不存在:"+methodName);
            }
            if (curMethod!=null){
                logger.debug("当前方法："+curMethod.getName());
                curVal = field.get(assignBean);
                //是否必须赋值参数
                if (isNotNull && (curVal==null || "".equals(curVal))){
                    logger.debug("必须赋值参数无值");
                    throw new IllegalArgumentException("必须赋值参数无值");
                }
                if(curVal!=null && !"".equals(curVal)) {
                    curMethod.invoke(assignedBean, curVal);
                    logger.debug("设值成功："+curVal);
                }
            }
        }
    }

}
